import numpy

import DecisionTree as DT
import numpy as np
import pandas as pd
import time
from sklearn.metrics import f1_score
from sklearn import datasets
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

def RandomForest(train, n_trees, min_sample, ip, jp):
    forest = []# 存放训练得到的所有的决策树
    fn = int(jp*(train.shape[1]-1))
    for n in range(n_trees):
        t1 = time.time()
        sf = np.random.choice(
                np.arange(1,train.shape[1]),
                fn,
                replace=False)
        sf = np.append(0,sf) # 保证label在第一列
        train_n = train.iloc[:,sf]
        p = np.random.random_sample()*(1-ip)+ip
        train_n = train_n.loc[
                np.random.choice(train_n.index,
                                 int(p*train_n.index.size),
                                 replace=False)]
        #train_n为随机选出的第n棵树的训练集
        forest.append(DT.build_tree(train_n, min_sample))
        t2 = time.time()
        print('构建第%d棵树的时间为%f'%(n,t2-t1))
    return forest   



def f_rate(forest, test):
    # 取出测试集中非标签属性的数据
    # 逐一获取样本的分类结果
    # 对比label属性的数据，确定分类是否准确
    y = test.pop(test.columns[0])
    length = y.size
    y_p = pd.Series([0]*length,index=y.index)
    n_trees = len(forest)
    res = [0]*n_trees # 存放每棵树的预测结果
    for i in range(length):
        x = test.iloc[i]
        for t in range(n_trees):
            res[t] = DT.classifier(forest[t],x)
        y_p.iloc[i] = max(res,key=res.count)
    score = f1_score(y,y_p.astype(np.int32),average='micro')
    return score
    
if __name__ == "__main__":
    test_f1 = []
    for i in range(10):
        cancer = datasets.load_breast_cancer()
        x = cancer.data
        y = cancer.target
        x = pd.DataFrame(cancer.data)
        y = pd.DataFrame(cancer.target)
        x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, shuffle=True)
        train = pd.concat([y_train, x_train], axis=1, ignore_index=True)
        test = pd.concat([y_test, x_test], axis=1, ignore_index=True)
        train = train.reset_index().iloc[:, 1:-1]
        test = test.reset_index().iloc[:, 1:-1]

        ip = 1
        jp = 0.6
        n_trees = i + 1
        min_sample = 10
        # 可调参数
        forest = RandomForest(train, n_trees, min_sample, ip, jp)
        t1 = time.time()
        score = f_rate(forest, test)
        test_f1.append(score)
        t2 = time.time()
        print('测试集分类时间为%f' % (t2 - t1))
        print('参数设置为n_trees=%d,min_sample=%d,ip=%f,jp=%f' % (n_trees, min_sample, ip, jp))
        print('分类正确率为%f' % score)
    x = np.linspace(1, 10, 10)
    plt.plot(test_f1, 'r', label='test_f1_score')
    plt.legend(loc='best')
    plt.xticks(x)
    plt.xlabel('n_trees')
    plt.ylabel('f1_score')
    plt.title('n_trees and f1_score')
    plt.show()
